package com.os.lambda.chapter5;

import com.os.lambda.chapter3.Artist;
import com.os.lambda.chapter3.StringLine;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static java.util.Arrays.asList;
import static java.util.stream.Collectors.*;

public class Chapter5 {

    public static void main(String[] args) {
        //String[] strArray = String[]::new;

        List<Integer> numbers = asList(1, 2, 3, 4);
        List<Integer> sameOrder = numbers.stream().collect(toList());
        System.out.println(sameOrder);

        System.out.println(StringLine.STRING_LINE);

        Set<Integer> numbers1 = new HashSet<>(asList(40, 3, 2, 1));
        List<Integer> sameOrder1 = numbers1.stream().collect(toList());
        System.out.println(sameOrder1);

        System.out.println(StringLine.STRING_LINE);

        Set<Integer> numbers2 = new HashSet<>(asList(40, 30, 20, 10));
        List<Integer> sameOrder2 = numbers2.stream().sorted().collect(toList());
        System.out.println(sameOrder2);

        System.out.println(StringLine.STRING_LINE);

        List<Integer> numbers3 = asList(100, 200, 300, 400);
        List<Integer> stillOrdered = numbers3.stream().map(x->x+1)
                .collect(toList());
        System.out.println(stillOrdered);

        Set<Integer> unordered = new HashSet<>(numbers3);
        List<Integer> stillUnOrdered = unordered.stream()
                .map(x->x+1)
                .collect(toList());
        System.out.println(stillUnOrdered);

        System.out.println(StringLine.STRING_LINE);

        /**
         * 使用流和收集器格式化艺术家姓名
         */
        List<Artist> artists = new ArrayList<>();
        String result = artists.stream().map(Artist::getName)
                .collect(Collectors.joining(",", "[", "]"));

        Stream<Album> albums = null;
        /**
         * 计算每个艺术家专辑数的简单方式
         */
        //Map<Artist, List<Album>> albumsByArtist =
        //        albums.collect(groupingBy(album -> album.getMainMusician()));

        System.out.println(StringLine.STRING_LINE);

        artists = asList(new Artist("a", "a"), new Artist("b", "b"), new Artist("c", "c"));
        StringBuilder builder = new StringBuilder("[");
        for(Artist artist : artists){
            if(builder.length()>1){
                builder.append(", ");
            }
            String name = artist.getName();
            builder.append(name);
        }
        builder.append("]");
        String result1 = builder.toString();
        System.out.println(result1);

        System.out.println(StringLine.STRING_LINE);

        System.out.println("采用forEach和StrngBuilder额实话艺术家姓名：");
        StringBuilder stringBuilder = new StringBuilder("[");
        artists.stream()
                .map(Artist::getName)
                .forEach(name->{
                    if(stringBuilder.length()>1)
                        stringBuilder.append(", ");
                    stringBuilder.append(name);
                });
        stringBuilder.append("]");
        System.out.println(stringBuilder.toString());

    }

    public Optional<Artist> biggestGroup(Stream<Artist> artistStream){
        Function<Artist, Long> getCount = artist -> artist.getMembers().stream().count();
        return artistStream.collect(maxBy(Comparator.comparing(getCount)));
    }

    public double averageNumbersOfTracks(List<Album> albums){
        return albums.stream()
                .collect(averagingInt(album->album.getTrackList().size()));
    }

    /**
     * 将艺术家组成的流分成乐队和独唱歌手两部分
     * @param artists
     * @return
     */
    public Map<Boolean, List<Artist>> bandsAndSolo(Stream<Artist> artists){
        return artists.collect(partitioningBy(artist -> artist.getSolo()));
    }

    /**
     * 使用引用方法
     */
    public Map<Boolean, List<Artist>> bandsAndSoloRef(Stream<Artist> artists){
        return artists.collect(partitioningBy(Artist::getSolo));
    }

    /**
     * 使用收集器计算每个艺术家专辑数量
     */
    public Map<Artist, Long> numberOfAlbums(Stream<Album> albums){
        return albums.collect(groupingBy(album -> album.getMainMusician(), counting()));
    }

    /**
     * 使用简单方式求每个艺术家的专辑名
     */
    public Map<Artist, List<String>> nameOfAlbumsDumb(Stream<Album> albums){
        Map<Artist, List<Album>> albumsByArtist =
                albums.collect(groupingBy(album -> album.getMainMusician()));

        Map<Artist, List<String>> nameOfAlbums = new HashMap<>();
        for(Map.Entry<Artist, List<Album>> entry : albumsByArtist.entrySet()){
            nameOfAlbums.put(entry.getKey(), entry.getValue()
                    .stream()
                    .map(Album::getName)
                    .collect(toList())
            );
        }
        return nameOfAlbums;
    }

    /**
     * 使用收集器求每个艺术家的专辑名
     */
    public Map<Artist, List<String>> nameOfAlbums(Stream<Album> albums){
        return albums.collect(groupingBy(Album::getMainMusician, mapping(Album::getName, toList())));
    }


}
